use crate::models::*;
use crate::{db, errors::MyError};
use actix::prelude::Addr;
use actix_protobuf::*;
use actix_redis::RedisActor;
use actix_web::*;
use deadpool_postgres::{Client, Pool};
use prost_derive::*;
use serde::{Deserialize, Serialize};

#[post("/notice")]
pub async fn notice(db_pool: web::Data<Pool>) -> Result<HttpResponse, Error> {
    let client: Client = db_pool.get().await.map_err(|err| MyError::PoolError(err))?;

    let notice = match db::get_notice(&client).await? {
        None => Notice {
            content: "".to_string(),
            time: "".to_string(),
        },
        Some(v) => v,
    };

    Ok(HttpResponse::Ok().json(notice))
}

#[derive(Clone, PartialEq, Message)]
pub struct Request {
    #[prost(string, tag = "1")]
    pub value: String,
}

#[derive(Serialize)]
pub struct Resp {
    pub token: String,
    pub servers: Vec<Server>,
}

#[post("/login/baowan")]
pub async fn login1(
    req: ProtoBuf<Request>,
    db_pool: web::Data<Pool>,
    redis: web::Data<Addr<RedisActor>>,
) -> Result<HttpResponse, Error> {
    if req.value.clone().len() > 1000 {
        return Ok(HttpResponse::InternalServerError().body("user_name too long"));
    }

    login(&req.value, db_pool, redis).await
}

//#[derive(Serialize, Deserialize)]
//pub struct ChuangKuRequest {
//    pub uid: String,
//    pub token: String,
//    #[serde(rename = "channelId")]
//    pub channel_id: String,
//    #[serde(rename = "gameId")]
//    pub game_id: String,
//}

#[post("/login/chuangku")]
pub async fn login2(
    req: ProtoBuf<Request>,
    db_pool: web::Data<Pool>,
    redis: web::Data<Addr<RedisActor>>,
) -> Result<HttpResponse, Error> {
    if req.value.clone().len() > 2000 {
        return Ok(HttpResponse::InternalServerError().body("user_name too long"));
    }

    match reqwest::Client::new()
        .post("http://ol.gzqudi.cn/qd/online/game/loginValidate")
        .body(req.value.clone())
        .send()
        .await
    {
        Ok(r) => {
            let changku_res: serde_json::Value = r.json().await.unwrap();

            let code: i64 = changku_res.get("resultCode").unwrap().as_i64().unwrap();
            if code == 1 {
                let chuangku_json: serde_json::Value = serde_json::from_str(&req.value).unwrap();
                let uid: &str = chuangku_json.get("uid").unwrap().as_str().unwrap();
                let name = "chuangku-".to_string() + uid;

                return login(&name, db_pool, redis).await;
            } else {
                let err_msg = serde_json::to_string(&changku_res).unwrap();
                return Ok(HttpResponse::InternalServerError().body(&err_msg));
            }
        }
        Err(err) => {
            return Ok(HttpResponse::InternalServerError().body(err.to_string()));
        }
    }
}

async fn login(
    name: &str,
    db_pool: web::Data<Pool>,
    redis: web::Data<Addr<RedisActor>>,
) -> Result<HttpResponse, Error> {
    let client: Client = db_pool.get().await.map_err(|err| MyError::PoolError(err))?;

    let user_id = match db::get_user(&client, name).await? {
        None => db::add_user(&client, name).await?,
        Some(user) => user.user_id,
    };

    let resp = Resp {
        token: db::create_token(user_id, redis).await,
        servers: db::get_servers(&client).await?,
    };

    Ok(HttpResponse::Ok().json(resp))
}
